package org.cassandraunit.spring;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import org.cassandraunit.CQLDataLoader;
import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.util.ClassUtils;
import org.springframework.util.ResourceUtils;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
/**
* The goal of this abstract listener is to provide utility methods for its subclasses to be able to :
* - start an embedded Cassandra
* - load dataset into Cassandra keyspace
*
* @author Gaƫtan Le Brun
*/
public abstract class AbstractCassandraUnitTestExecutionListener extends AbstractTestExecutionListener implements Ordered {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(CassandraUnitTestExecutionListener.class);
private static boolean initialized = false;
protected void startServer(TestContext testContext) throws Exception {
EmbeddedCassandra embeddedCassandra = Preconditions.checkNotNull(
AnnotationUtils.findAnnotation(testContext.getTestClass(), EmbeddedCassandra.class),
"CassandraUnitTestExecutionListener must be used with @EmbeddedCassandra on " + testContext.getTestClass());
if (!initialized) {
String yamlFile = Optional.fromNullable(embeddedCassandra.configuration()).get();
long timeout = embeddedCassandra.timeout();
EmbeddedCassandraServerHelper.startEmbeddedCassandra(yamlFile, timeout);
initialized = true;
}
CassandraDataSet cassandraDataSet = AnnotationUtils.findAnnotation(testContext.getTestClass(), CassandraDataSet.class);
if (cassandraDataSet != null) {
List<String> dataset = null;
ListIterator<String> datasetIterator = null;
String keyspace = cassandraDataSet.keyspace();
dataset = dataSetLocations(testContext, cassandraDataSet);
datasetIterator = dataset.listIterator();
CQLDataLoader cqlDataLoader = new CQLDataLoader(EmbeddedCassandraServerHelper.getSession());
while (datasetIterator.hasNext()) {
String next = datasetIterator.next();
boolean dropAndCreateKeyspace = datasetIterator.previousIndex() == 0;
cqlDataLoader.load(new ClassPathCQLDataSet(next, dropAndCreateKeyspace, dropAndCreateKeyspace, keyspace));
}
}
}
private List<String> dataSetLocations(TestContext testContext, CassandraDataSet cassandraDataSet) {
String[] dataset = cassandraDataSet.value();
if (dataset.length == 0) {
String alternativePath = alternativePath(testContext.getTestClass(), true, cassandraDataSet.type().name());
if (testContext.getApplicationContext().getResource(alternativePath).exists()) {
dataset = new String[]{alternativePath.replace(ResourceUtils.CLASSPATH_URL_PREFIX + "/", "")};
} else {
alternativePath = alternativePath(testContext.getTestClass(), false, cassandraDataSet.type().name());
if (testContext.getApplicationContext().getResource(alternativePath).exists()) {
dataset = new String[]{alternativePath.replace(ResourceUtils.CLASSPATH_URL_PREFIX + "/", "")};
} else {
LOGGER.info("No dataset will be loaded");
}
}
}
return Arrays.asList(dataset);
}
protected void cleanServer() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
protected String alternativePath(Class<?> clazz, boolean includedPackageName, String extension) {
if (includedPackageName) {
return ResourceUtils.CLASSPATH_URL_PREFIX + "/" + ClassUtils.convertClassNameToResourcePath(clazz.getName()) + "-dataset" + "." + extension;
} else {
return ResourceUtils.CLASSPATH_URL_PREFIX + "/" + clazz.getSimpleName() + "-dataset" + "." + extension;
}
}
@Override
public int getOrder() {
// since spring 4.1 the default-order is LOWEST_PRECEDENCE. But we want to start EmbeddedCassandra even before
// the springcontext such that beans can connect to the started cassandra
return 0;
}
}